﻿using Notoric.Commanding.CommandBase;
using LukasKopenec.LocalizationSupport;

namespace Notoric.ViewModel
{
    /// <summary>
    /// Implements an undoable command for renaming a resource part.
    /// </summary>
    /// <remarks>
    /// Input Parameters:
    /// <list type="table">
    /// <listheader>
    /// <term>
    ///     Name
    /// </term>
    /// <description>
    ///     Description
    /// </description>
    /// </listheader>
    /// <item>
    /// <term>
    ///     RenamedPart (<see cref="Elements.Resource"/>)
    /// </term>
    /// <description>
    ///     The renamed part.
    /// </description>
    /// </item>
    /// <item>
    /// <term>
    ///     VirtualPath (<see cref="string"/>)
    /// </term>
    /// <description>
    ///     The new virtual path.
    /// </description>
    /// </item>
    /// </list>
    /// The command can execute if all of its parameters are set to non-null values
    /// and the <see cref="Model.Elements.ProjectElement.Resources"/> contains a mapping 
    /// for <see cref="RenamedPart"/>, but does not contain any mapping 
    /// for the <see cref="VirtualPath"/>.
    /// </remarks>
    public class RenameResourceCommand : UndoableCommandBase
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="RenameResourceCommand"/> instance.
        /// </summary>
        /// <param name="undoStack">
        /// <para>
        /// Type: <see cref="CommandStack"/>
        /// </para>
        /// <para>
        /// The command stack on which the command will be put after its execution.
        /// </para>
        /// </param>
        /// <param name="redoStack">
        /// <para>
        /// Type: <see cref="CommandStack"/>
        /// </para>
        /// <para>
        /// The command stack on which the command will be put when it has been undone.
        /// </para>
        /// </param>
        public RenameResourceCommand(CommandStack undoStack, CommandStack redoStack)
            : base(undoStack, redoStack)
        {
            AddParameter<Elements.Resource>("RenamedPart", ParameterDirection.In);
            AddParameter<string>("VirtualPath", ParameterDirection.In);

            Name = (string)LocalizationManager.GetValue("Commands.Names.Rename");
        }

        #endregion

        #region Command Logic

        /// <inheritdoc/>
        protected override void CommandOperation(object parameter)
        {
            oldPath = RenamedPart.AdaptedPart.Package.ProjectPart.Project.Resources[RenamedPart.AdaptedPart.Uri];
            RenamedPart.AdaptedPart.Package.ProjectPart.Project.Resources.RenamePart(RenamedPart.AdaptedPart.Uri, VirtualPath);
        }

        /// <inheritdoc/>
        protected override void RedoOperation()
        {
            RenamedPart.AdaptedPart.Package.ProjectPart.Project.Resources.RenamePart(RenamedPart.AdaptedPart.Uri, VirtualPath);
        }

        /// <inheritdoc/>
        protected override void UndoOperation()
        {
            RenamedPart.AdaptedPart.Package.ProjectPart.Project.Resources.RenamePart(RenamedPart.AdaptedPart.Uri, oldPath);
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the renamed resource.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Elements.Resource"/>
        /// </para>
        /// <para>
        /// The renamed resource.<br/>
        /// This property wraps the "RenamedPart" command parameter.
        /// </para>
        /// </value>
        public Elements.Resource RenamedPart
        {
            get { return GetParameterValue<Elements.Resource>("RenamedPart"); }
            set { SetParameterValue<Elements.Resource>("RenamedPart", value); }
        }

        /// <summary>
        /// Gets or sets the new virtual path.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="string"/>
        /// </para>
        /// <para>
        /// The new virtual path.<br/>
        /// This property wraps the "VirtualPath" command parameter.
        /// </para>
        /// </value>
        public string VirtualPath
        {
            get { return GetParameterValue<string>("VirtualPath"); }
            set { SetParameterValue<string>("VirtualPath", value); }
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the old virtual path.
        /// </summary>
        private string oldPath;

        #endregion
    }
}
